package com.kordar.admin.modular.sys.controller;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.*;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.kordar.admin.enums.CommonActive;
import com.kordar.admin.enums.EnumUtils;
import com.kordar.admin.kernel.wrapper.BatchDeleteWrapperEntity;
import com.kordar.admin.kernel.wrapper.UpdateWrapperEntity;
import com.kordar.admin.modular.sys.entity.DatasourceEntity;
import com.kordar.admin.modular.sys.service.DatasourceService;
import com.kordar.datalist.DatalistService;
import com.kordar.datalist.ResultEntity;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.sql.DataSource;
import java.util.Map;
import java.util.Set;

@AllArgsConstructor
@Controller
@RequestMapping("sys")
public class DatasourceController {

    private final DatasourceService datasourceService;
    private final DatalistService datalistService;
    private final DynamicRoutingDataSource ds;
    private final DruidDataSourceCreator druidDataSourceCreator;

    @ModelAttribute("activeLabels")
    public Map<Integer, String> active() {
        return EnumUtils.EnumToMapInt(CommonActive.class);
    }

    @GetMapping("datasource/index")
    public String index(Model model) {
        model.addAttribute("data", datalistService.render(datasourceService.list(), DatasourceEntity.class));
        return "pages/modular/system/datasource/index";
    }

    @GetMapping("datasource/form")
    public String form(Model model, @RequestParam(required = false, defaultValue = "") String name) {
        if (name.equals("")) {
            model.addAttribute("header", "新建数据源");
            model.addAttribute("datasource", new DatasourceEntity());
        } else {
            model.addAttribute("header", "修改数据源");
            model.addAttribute("isUpdate", true);
            model.addAttribute("datasource", datasourceService.getById(name));
        }

        return "pages/modular/system/datasource/form";
    }

    @PostMapping("datasource/save")
    @ResponseBody
    public ResultEntity<Object> save(@Validated DatasourceEntity datasourceEntity) {
        if (datasourceService.saveOrUpdate(datasourceEntity)) {
            if (datasourceEntity.getActive().equals(CommonActive.OPEN.getCode())) {
                addDruid(datasourceEntity);
            } else {
                removeDruid(datasourceEntity);
            }
        }

        return ResultEntity.success();
    }

    @RequestMapping("datasource/switch")
    @ResponseBody
    public ResultEntity<Object> active(String name, Integer active) {
        DatasourceEntity entity = datasourceService.getById(name);
        entity.setActive(active);
        if (datasourceService.updateById(entity)) {
            if (entity.getActive().equals(CommonActive.OPEN.getCode())) {
                addDruid(entity);
            } else {
                removeDruid(entity);
            }
        }
        return ResultEntity.success();
    }

    @RequestMapping("datasource/edit")
    @ResponseBody
    public ResultEntity<Object> edit(@RequestBody UpdateWrapperEntity<DatasourceEntity> entity) {
        UpdateWrapper<DatasourceEntity> query = entity.where(DatasourceEntity.class).data().getQuery();
        datasourceService.update(query);
        return ResultEntity.success();
    }

    @PostMapping("datasource/delete")
    @ResponseBody
    public ResultEntity<Object> del(String name) {
        datasourceService.removeById(name);
        removeDruid(name);
        return ResultEntity.success();
    }

    @RequestMapping("datasource/batch-delete")
    @ResponseBody
    public ResultEntity<Object> del(@RequestBody BatchDeleteWrapperEntity<String> entity) {
        Set<String> ids = entity.getIds();
        datasourceService.removeByIds(ids);
        ids.forEach(this::removeDruid);
        return ResultEntity.success();
    }

    private void addDruid(DatasourceEntity entity) {
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        BeanUtils.copyProperties(entity, dataSourceProperty);
        DataSource dataSource = druidDataSourceCreator.createDataSource(dataSourceProperty);
        ds.addDataSource(entity.getName(), dataSource);
    }

    private void removeDruid(DatasourceEntity entity) {
        ds.removeDataSource(entity.getName());
    }

    private void removeDruid(String name) {
        ds.removeDataSource(name);
    }

}
